Openlayers中多边形的聚合

您所在的位置:网站首页 openlayers webglpoints聚合 Openlayers中多边形的聚合

Openlayers中多边形的聚合

2024-07-15 20:34| 来源: 网络整理| 查看: 265

关于OpenLayers的Cluster

ol.source.Cluster

ol利用这个js对象实现对地图上feature进行聚合展示的控制,所有的features需要被放在一个feature数组中作为ol.source.Vector中features属性进行载入。

下面就是官方针对Cluster的API文档:

new ol.source.Cluster(options)

options: Constructor options.

NameTypeDescriptionattributionsol.AttributionLikeAttributions.distancenumberMinimum distance in pixels between clusters. Default is 20.extentol.ExtentExtent.geometryFunctionfunctionFunction that takes an ol.Feature as argument and returns an ol.geom.Point as cluster calculation point for the feature. When a feature should not be considered for clustering, the function should return null. The default, which works when the underyling source contains point features only, is function(feature) {return feature.getGeometry();} See ol.geom.Polygon#getInteriorPoint for a way to get a cluster calculation point for polygons.formatol.format.FeatureFormat.logostringLogo.projectionol.ProjectionLikeProjection.sourceol.source.VectorSource. Required.wrapXbooleanWrapX. Default is true

之所以把这个贴出来是为了让大家了解一个事情,那就是如果在Openlayers的官方API文档中找你想要的东西,恐怕应该是一件需要碰运气的事情。并不是说他们的文档写的不够全面和完善,但当你想要从这种API文档中快速的找到一些能够立即实现你想要的开发效果的东西,那恐怕你得把他当前API所涉及到的所有js对象的API都看一遍才行了(事实上我就是这么做的)。本文的目的只是让有GIS js开发基础的人能够快速的用openlayers实现多边形聚合效果,因为在网上搜了很久都没有类似的贴,所以才决定记录下来,希望有可能帮助到遇到类似情况的人吧。

实现多边形聚合效果

在网上翻了很多关于ol实现聚合的贴,基本上都是照本宣科搞几个ol.geom.Point随便弄一弄,然而我遇到的需求是我可能会get两百个左右的ol.geom.Polygon,按照官网给的例子,根本行不通啊喂,报的错也让我很崩溃,说我的操作有问题。马德我一个塞尔达可以单挑人马活下来的人说我操作有问题我摔。

愤怒的我立即打开F12开始不断的试错,试图证明我操作的问题是ol本身的问题引起的,后来API中的一个option让我产生了想法,就是上面的那个geometryFunction,这个function可以将feature获取到并且返回一个Point作为feature本身的聚合坐标,只要不妨碍进行聚合的计算,即使返回极点他也不拦着你,不过一般的Polygon都有一个getInteriorPoint方法可以获取多边形的内点,所以在geometryFunction中可以做到返回多边形内点坐标(那么问题就来了,内点是哪个点呢,其实我也不知道,原谅我调试的时候没有多去试试)。

代码中把geometryFunction属性加上,写一个新的方法去获取多边形内点并返回。

var geometryFunc = function (feature) { return feature.getGeometry().getInteriorPoint(); } var vectorLayer = new ol.layer.Vector({ source: new ol.source.Cluster({ distance: distance, //调用方法时候输入的聚合距离 source: new ol.source.Vector({ features: features }), //获取到的feature数组 geometryFunction: geometryFunc //获取多边形内点的方法 }) });

然后保存刷新页面,查询一下,最后发现聚合效果正常运转,我的操作终于没问题了。

但是放大以后,我勒个擦,这些小圆圈是什么鬼,我的多边形呢?

于是陷入了第二波痛苦。

直到在官方demo里面看到一个这样的example:Earthquake Cluster

然后打开了通往新世界的大门。 在ol.layer.Vector中有一个style属性,用来将获取到的feature和resolution进行处理,如下:

var maxFeatureCount, vector; // 计算当前resolution下feature之间的距离以形成聚合图形的基础信息 function calculateClusterInfo(resolution) { maxFeatureCount = 0; var features = vector.getSource().getFeatures(); var feature, radius; for (var i = features.length - 1; i >= 0; --i) { feature = features[i]; var originalFeatures = feature.get('features'); var extent = ol.extent.createEmpty(); var j, jj; for (j = 0, jj = originalFeatures.length; j < jj; ++j) { ol.extent.extend(extent, originalFeatures[j].getGeometry().getExtent()); } maxFeatureCount = Math.max(maxFeatureCount, jj); radius = 0.25 * (ol.extent.getWidth(extent) + ol.extent.getHeight(extent)) /resolution; feature.set('radius', radius); } } var currentResolution; function styleFunction(feature, resolution) { if (resolution != currentResolution) { // 根据resolution处理图形聚合状态 calculateClusterInfo(resolution); currentResolution = resolution; } var style; var size = feature.get('features').length; if (size > 1) { // 聚合图形样式,自动获取对应半径,调整颜色深度 style = new ol.style.Style({ image: new ol.style.Circle({ radius: feature.get('radius'), fill: new ol.style.Fill({ color: [255, 153, 0, Math.min(0.8, 0.4 + (size / maxFeatureCount))] }) }), text: new ol.style.Text({ text: size.toString(), fill: textFill, stroke: textStroke }) }); } else { var originalFeature = feature.get('features')[0]; // 单个图形样式处理方法 style = createPolygonStyle(originalFeature); } return style; } vector = new ol.layer.Vector({ source: new ol.source.Cluster({ distance: 40, source: new ol.source.Vector({ //获取到的feature数组 feature: features }) }), style: styleFunction });

这个方法首先对返回的resolution进行了判断,如果地图进行了缩放,则重新计算图面上点与点之间的距离以规划聚合图形的半径,然后对其返回对应单独的图形样式。

接下来就要单独讲讲上面单个图形样式处理方法的部分,由于在我的需求中,对每个图形还单独增加了点击效果,聚合图形不考虑在内,但凡出现没有在聚合范围内的Polygon,都要求能够点击并且高亮展示,所以上文的createPolygonStyle方法还需进行进一步的处理;首先在全局变量中需要添加一个highLightFeatureId用于记录哪个Polygon是需要高亮的,然后在styleFunction回调的时候对需要高亮的图形样式进行调整,代码如下:

var createPolygonStyle = function (feature) { if (_highlightfeatureId == feature.attributes.id) { // 高亮样式 var style = new ol.style.Style({ geometry: feature.getGeometry(), fill: new ol.style.Fill({ color: 'rgba(204,102,102,0.8)' }), stroke: new ol.style.Stroke({ color: '#CC3333', width: 3 }), image: new ol.style.Circle({ stroke: new ol.style.Stroke({ color: 'rgb(204,102,102)', width: 1 }), radius: 6, fill: new ol.style.Fill({ color: [255, 255, 255, 0.6] }) }), text: new ol.style.Text({ text: feature.text, textAlign: "center", textBaseline: 'middle', font: "14px serif", fill: new ol.style.Fill({ color: "#FFFFFF" }), stroke: new ol.style.Stroke({ color: "#000000", width: 3 }) }) }); return style; } else { // 普通多边形的样式 var style = new ol.style.Style({ geometry: feature.getGeometry(), fill: new ol.style.Fill({ color: 'rgba(0,204,204,0.2)' }), stroke: new ol.style.Stroke({ lineDash: [20, 20], color: '#0099CC', width: 1 }), image: new ol.style.Circle({ stroke: new ol.style.Stroke({ color: 'rgb(0,204,204)', width: 1 }), radius: 6, fill: new ol.style.Fill({ color: [255, 255, 255, 0.6] }) }), text: new ol.style.Text({ text: feature.text, textAlign: "center", textBaseline: 'middle', font: "14px serif", fill: new ol.style.Fill({ color: "#FFFFFF" }), stroke: new ol.style.Stroke({ color: "#000000", width: 3 }) }) }); return style; } }

最后附上实现效果图 小比例尺

大比例尺

小比例尺高亮

大比例尺高亮

高亮后聚合

作者:MMMOOO 链接:https://www.jianshu.com/p/330b45f1c9ac 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3